using Circus.CodeEditor;
using Circus.CodeEditor.Dialogs;
using Circus.CodeEditor.Serialization;
using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Drawing.Printing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Circus.CodeEditor
{
	[ToolboxItem(false)]
	public class Printing : IDisposable
	{
		private CodeEditor owner;
		private CodeEditor printEdit;
		private EditorPrintDocument printDocument;
		private PrintOptions options;
		private PrintOptions allowedOptions;
		private PrinterSettings printerSettings;
		private PrintDialog printDialog;
		private PageSetupDialog pageSetupDialog;
		private PrintPreviewDialog printPreviewDialog;
		private DlgPrintOptions printOptionsDialog;
		private HookHandler hookProc;
		private IntPtr hookHandle = IntPtr.Zero;
		private IntPtr lastWnd = IntPtr.Zero;
		private bool dialogCalled;
		private bool showPrintOptionsDialog;

	    [Browsable(false)]
	    public event CreatePrintEditEvent CreatePrintEdit;

	    [Browsable(false)]
	    public event EventHandler Initialized;

	    [Browsable(false)]
	    public event EventHandler Finalized;
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual PrintDocument PrintDocument
		{
			get
			{
				return this.printDocument;
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual PrinterSettings PrinterSettings
		{
			get
			{
				return this.printerSettings;
			}
		}
		[Description("Gets or sets \"PrintOptions\" that determines printing behaviour."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
		public virtual PrintOptions Options
		{
			get
			{
				return this.options;
			}
			set
			{
				if (this.options != value)
				{
					this.options = value;
					this.OnOptionsChanged();
				}
			}
		}
		[Description("Gets or sets Print Options dialog options, that can be changed by user."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
		public virtual PrintOptions AllowedOptions
		{
			get
			{
				return this.owner.Selection.IsEmpty ? this.allowedOptions : (this.allowedOptions | PrintOptions.PrintSelection);
			}
			set
			{
				if (this.allowedOptions != value)
				{
					this.allowedOptions = value;
					this.OnAllowedOptionsChanged();
				}
			}
		}
		
	
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual PrintDialog PrintDialog
		{
			get
			{
				if (this.printDialog == null)
				{
					this.printDialog = new PrintDialog();
					this.printDialog.UseEXDialog = true;
					this.printDialog.Document = this.printDocument;
					this.printDialog.PrinterSettings = this.printerSettings;
					this.printDialog.AllowSomePages = true;
					this.printDialog.ShowHelp = true;
					this.printDialog.HelpRequest += new EventHandler(this.DoHelpRequest);
				}
				return this.printDialog;
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual PageSetupDialog PageSetupDialog
		{
			get
			{
				if (this.pageSetupDialog == null)
				{
					this.pageSetupDialog = new PageSetupDialog();
					this.pageSetupDialog.Document = this.printDocument;
					this.pageSetupDialog.PageSettings = new PageSettings(this.printerSettings);
					this.pageSetupDialog.PrinterSettings = this.printerSettings;
				}
				return this.pageSetupDialog;
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual PrintPreviewDialog PrintPreviewDialog
		{
			get
			{
				if (this.printPreviewDialog == null)
				{
					this.printPreviewDialog = new PrintPreviewDialog();
					this.printPreviewDialog.Document = this.printDocument;
				}
				return this.printPreviewDialog;
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public CodeEditor PrintEdit
		{
			get
			{
				return this.printEdit;
			}
		}
		[DefaultValue(false)]
		public virtual bool ShowPrintOptionsDialog
		{
			get
			{
				return this.showPrintOptionsDialog;
			}
			set
			{
				if (this.showPrintOptionsDialog != value)
				{
					this.showPrintOptionsDialog = value;
					this.OnShowPrintOptionsDialogChanged();
				}
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual DlgPrintOptions PrintOptionsDialog
		{
			get
			{
				if (this.printOptionsDialog == null)
				{
					this.printOptionsDialog = new DlgPrintOptions();
				}
				return this.printOptionsDialog;
			}
			set
			{
				if (this.printOptionsDialog != value)
				{
					this.printOptionsDialog = value;
					this.OnPrintOptionsDialogChanged();
				}
			}
		}
	 
		private bool EnumDialogChilds(IntPtr hwnd, IntPtr lParam)
		{
			bool result;
			if (string.Compare(OSUtils.GetText(hwnd), "&Help", true) == 0)
			{
				OSUtils.SetText(hwnd, StringConsts.PrintOptionsButtonText);
				this.lastWnd = IntPtr.Zero;
				result = false;
			}
			else
			{
				if (string.Compare(OSUtils.GetClassName(hwnd), "Button", true) == 0)
				{
					this.lastWnd = hwnd;
				}
				result = true;
			}
			return result;
		}
		private IntPtr DialogHook(int ncode, IntPtr wParam, IntPtr lParam)
		{
			if (ncode == 0 && !this.dialogCalled)
			{
				OSUtils.CWPSTRUCT cWPSTRUCT = (OSUtils.CWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(OSUtils.CWPSTRUCT));
				if (cWPSTRUCT.message == 272)
				{
					this.lastWnd = IntPtr.Zero;
					OSUtils.EnumChildWindows(cWPSTRUCT.hwnd, new EnumChildProc(this.EnumDialogChilds), IntPtr.Zero);
					if (this.lastWnd != IntPtr.Zero)
					{
						OSUtils.SetText(this.lastWnd, StringConsts.PrintOptions);
					}
					this.dialogCalled = true;
				}
			}
			return OSUtils.CallNextHook(this.hookHandle, ncode, wParam, lParam);
		}
		private void HookPrintDialog()
		{
			this.dialogCalled = false;
			this.hookProc = new HookHandler(this.DialogHook);
			this.hookHandle = OSUtils.SetWndProcHook(this.hookProc);
		}
		private void UnhookPrintDialog()
		{
			if (this.hookHandle != IntPtr.Zero)
			{
				OSUtils.ReleaseHook(this.hookHandle);
				this.hookHandle = IntPtr.Zero;
				this.hookProc = null;
			}
		}
		private void DoHelpRequest(object sender, EventArgs e)
		{
			if (this.showPrintOptionsDialog && this.PrintOptionsDialog != null && this.ExecutePrintOptionsDialog() == DialogResult.OK)
			{
				this.Options = this.PrintOptionsDialog.Options;
			}
		}
		protected virtual void OnOptionsChanged()
		{
		}
		protected virtual void OnAllowedOptionsChanged()
		{
		}
		protected virtual void OnHeaderChanged()
		{
		}
		protected virtual void OnFooterChanged()
		{
		}
		protected virtual void OnShowPrintOptionsDialogChanged()
		{
		}
		protected virtual void OnPrintOptionsDialogChanged()
		{
		}
		public Printing(CodeEditor owner)
		{
			this.owner = owner;
			this.printerSettings = new PrinterSettings();
			this.printDocument = this.CreatePrintDocument();
			this.printDocument.PrinterSettings = this.printerSettings;
			this.options = EditConsts.DefaultPrintOptions;
			this.allowedOptions = EditConsts.DefaultPrintOptions;
		}
		~Printing()
		{
			this.Dispose(false);
		}
		protected virtual EditorPrintDocument CreatePrintDocument()
		{
			return new EditorPrintDocument(this, this.printerSettings);
		}
		public virtual CodeEditor OnCreatePrintEdit()
		{
			this.printEdit = null;
			if (this.CreatePrintEdit != null)
			{
				CreatePrintEditEventArgs createPrintEditEventArgs = new CreatePrintEditEventArgs();
				this.CreatePrintEdit(this, createPrintEditEventArgs);
				if (createPrintEditEventArgs.PrintEdit != null)
				{
					this.printEdit = createPrintEditEventArgs.PrintEdit;
				}
			}
			if (this.printEdit == null)
			{
				this.printEdit = new CodeEditor();
			}
			return this.printEdit;
		}
		public virtual void OnInitialized()
		{
			if (this.Initialized != null)
			{
				this.Initialized(this, EventArgs.Empty);
			}
		}
		public virtual void OnFinalized()
		{
			this.printEdit = null;
			if (this.Finalized != null)
			{
				this.Finalized(this, EventArgs.Empty);
			}
		}
	
		public virtual DialogResult ExecutePrintPreviewDialog()
		{
			return this.ExecutePrintPreviewDialog(null);
		}
		public virtual DialogResult ExecutePrintPreviewDialog(IWin32Window ownerwnd)
		{
			this.printDocument.Init(this.owner);
			DialogResult result;
			try
			{
				this.PrintPreviewDialog.StartPosition = FormStartPosition.CenterParent;
				result = ((ownerwnd != null) ? this.PrintPreviewDialog.ShowDialog(ownerwnd) : this.PrintPreviewDialog.ShowDialog());
			}
			catch
			{
				result = DialogResult.Cancel;
			}
			return result;
		}
		public virtual DialogResult ExecutePrintDialog()
		{
			return this.ExecutePrintDialog(null);
		}
		public virtual DialogResult ExecutePrintDialog(IWin32Window ownerwnd)
		{
			this.printDocument.Init(this.owner, true);
			DialogResult result;
			try
			{
				DialogResult dialogResult;
				if (this.PrintDialog.ShowHelp)
				{
					this.HookPrintDialog();
					try
					{
						dialogResult = ((ownerwnd != null) ? this.PrintDialog.ShowDialog(ownerwnd) : this.PrintDialog.ShowDialog());
					}
					finally
					{
						this.UnhookPrintDialog();
					}
				}
				else
				{
					dialogResult = ((ownerwnd != null) ? this.PrintDialog.ShowDialog(ownerwnd) : this.PrintDialog.ShowDialog());
				}
				result = dialogResult;
			}
			catch
			{
				result = DialogResult.Cancel;
			}
			return result;
		}
		public virtual DialogResult ExecutePageSetupDialog()
		{
			return this.ExecutePageSetupDialog(null);
		}
		public virtual DialogResult ExecutePageSetupDialog(IWin32Window ownerwnd)
		{
			this.printDocument.Init(this.owner);
			DialogResult result;
			try
			{
				result = ((ownerwnd != null) ? this.PageSetupDialog.ShowDialog(ownerwnd) : this.PageSetupDialog.ShowDialog());
			}
			catch
			{
				result = DialogResult.Cancel;
			}
			return result;
		}
		public virtual DialogResult ExecutePrintOptionsDialog()
		{
			return this.ExecutePrintOptionsDialog(null);
		}
		public virtual DialogResult ExecutePrintOptionsDialog(IWin32Window ownerwnd)
		{
			DialogResult result;
			if (this.PrintOptionsDialog == null)
			{
				result = DialogResult.None;
			}
			else
			{
				this.PrintOptionsDialog.Options = this.Options;
				this.PrintOptionsDialog.AllowedOptions = this.AllowedOptions;
				this.PrintOptionsDialog.FileName = this.owner.Source.FileName;
				result = ((ownerwnd != null) ? this.PrintOptionsDialog.ShowDialog(ownerwnd) : this.PrintOptionsDialog.ShowDialog());
			}
			return result;
		}
		public virtual void ResetOptions()
		{
			this.Options = EditConsts.DefaultPrintOptions;
		}
		public virtual void ResetAllowedOptions()
		{
			this.AllowedOptions = EditConsts.DefaultPrintOptions;
		}
		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (this.printEdit != null)
				{
					((IDisposable)this.printEdit).Dispose();
					this.printEdit = null;
				}
				if (this.printDocument != null)
				{
					this.printDocument.Dispose();
					this.printDocument = null;
				}
			
			}
		}
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}
	}
}
